"""技能模型"""

from typing import List, Dict, Any, Optional
from enum import Enum
from pydantic import BaseModel, Field
from .character import Character
from .battlefield import Battlefield
import random


class SkillType(Enum):
    """技能类型"""
    DAMAGE = "damage"      # 伤害技能
    HEAL = "heal"          # 治疗技能
    BUFF = "buff"          # 增益技能
    DEBUFF = "debuff"      # 减益技能
    PASSIVE = "passive"    # 被动技能
    UTILITY = "utility"    # 功能技能


class TargetType(Enum):
    """目标类型"""
    SINGLE = "single"      # 单体目标
    AREA = "area"          # 范围目标
    SELF = "self"          # 自身目标


class SkillEffect(BaseModel):
    """技能效果"""
    target_id: str = Field(..., description="目标角色ID")
    effect_value: int = Field(..., description="效果数值")
    effect_type: str = Field(..., description="效果类型(damage/heal)")
    
    # 战斗详情
    is_hit: bool = Field(True, description="是否命中")
    is_crit: bool = Field(False, description="是否暴击")
    is_dodged: bool = Field(False, description="是否闪避")


class Skill(BaseModel):
    """技能类"""
    
    id: str = Field(..., description="技能ID")
    name: str = Field(..., description="技能名称")
    skill_type: SkillType = Field(..., description="技能类型")
    target_type: TargetType = Field(..., description="目标类型")
    
    # 技能属性
    base_value: int = Field(0, description="基础数值")
    percentage_value: int = Field(0, description="百分比数值(基于攻击力)")
    range_size: int = Field(0, description="作用范围(仅范围技能有效)")
    max_distance: int = Field(3, description="最大释放距离")
    cost: int = Field(0, description="消耗(预留字段)")
    cooldown: int = Field(0, description="冷却时间(预留字段)")
    
    # 技能效果
    effects: List[Dict[str, Any]] = Field(default_factory=list, description="技能效果列表")
    
    # 技能描述
    description: str = Field("", description="技能描述")
    
    def calculate_effect_value(self, caster: Character, target: Character = None) -> int:
        """计算技能效果数值"""
        # 计算百分比伤害
        percentage_damage = int(caster.attack * self.percentage_value / 100)
        
        if self.skill_type == SkillType.DAMAGE:
            # 伤害 = 基础数值 + 百分比伤害 (防御力在take_damage中处理)
            return self.base_value + percentage_damage
        elif self.skill_type == SkillType.HEAL:
            # 治疗 = 基础数值 + 百分比治疗
            return self.base_value + percentage_damage
        return self.base_value + percentage_damage
    
    def get_targets(self, caster: Character, target_x: int, target_y: int, 
                   battlefield: Battlefield, all_characters: List[Character]) -> List[Character]:
        """获取技能目标"""
        targets = []
        
        if self.target_type == TargetType.SINGLE:
            # 单体目标
            target = battlefield.get_character_at_position(target_x, target_y, all_characters)
            if target and target.is_alive:
                targets.append(target)
        
        elif self.target_type == TargetType.AREA:
            # 范围目标
            targets = battlefield.get_characters_in_range(
                target_x, target_y, self.range_size, all_characters
            )
            # 只选择存活的角色
            targets = [t for t in targets if t.is_alive]
        
        elif self.target_type == TargetType.SELF:
            # 自身目标
            if caster.is_alive:
                targets.append(caster)
        
        return targets
    
    def execute(self, caster: Character, target_x: int, target_y: int, 
                battlefield: Battlefield, all_characters: List[Character]) -> List[SkillEffect]:
        """执行技能"""
        effects = []
        
        # 被动技能不需要主动执行
        if self.skill_type == SkillType.PASSIVE:
            return effects
        
        targets = self.get_targets(caster, target_x, target_y, battlefield, all_characters)
        
        for target in targets:
            # 在处理每个目标前，再次检查目标是否存活
            # 这对于群攻技能很重要，因为前面的攻击可能已经杀死了某些目标
            if not target.is_alive:
                continue
                
            # 检查技能类型和目标类型是否匹配
            if self.skill_type == SkillType.DAMAGE:
                # 伤害技能只能对敌方使用
                if caster.character_type != target.character_type:
                    effect_value = self.calculate_effect_value(caster, target)
                    
                    # 计算命中和暴击
                    is_hit = random.randint(1, 100) <= caster.hit_rate
                    is_crit = False
                    
                    if is_hit:
                        is_crit = caster.calculate_crit_chance()
                    
                    # 应用伤害
                    damage_result = target.take_damage(effect_value, is_crit=is_crit, is_hit=is_hit)
                    
                    # 创建技能效果
                    effect = SkillEffect(
                        target_id=target.id,
                        effect_value=damage_result['actual_damage'],
                        effect_type="damage"
                    )
                    
                    # 添加战斗详情到效果中
                    effect.is_hit = damage_result['is_hit']
                    effect.is_crit = damage_result['is_crit']
                    effect.is_dodged = damage_result['is_dodged']
                    
                    effects.append(effect)
            
            elif self.skill_type == SkillType.HEAL:
                # 治疗技能只能对友方使用，且目标必须存活
                if caster.character_type == target.character_type or target == caster:
                    effect_value = self.calculate_effect_value(caster, target)
                    actual_heal = target.heal(effect_value)
                    
                    effect = SkillEffect(
                        target_id=target.id,
                        effect_value=actual_heal,
                        effect_type="heal"
                    )
                    
                    # 治疗技能总是命中
                    effect.is_hit = True
                    effect.is_crit = False
                    effect.is_dodged = False
                    
                    effects.append(effect)
            
            elif self.skill_type == SkillType.BUFF:
                # 增益技能只能对友方使用，且目标必须存活
                if caster.character_type == target.character_type or target == caster:
                    self._apply_effects(caster, target, effects)
            
            elif self.skill_type == SkillType.DEBUFF:
                # 减益技能只能对敌方使用，且目标必须存活
                if caster.character_type != target.character_type:
                    self._apply_effects(caster, target, effects)
            
            elif self.skill_type == SkillType.UTILITY:
                # 功能技能可以对任何目标使用，但目标必须存活
                self._apply_effects(caster, target, effects)
        
        return effects
    
    def _apply_effects(self, caster: Character, target: Character, effects: List[SkillEffect]):
        """应用技能效果"""
        for effect_data in self.effects:
            effect_type = effect_data.get("type")
            
            if effect_type == "buff":
                # 属性增益
                attribute = effect_data.get("attribute")
                value = effect_data.get("value", 0)
                duration = effect_data.get("duration", 1)
                
                # 这里应该添加到角色的buff列表中，暂时直接修改属性
                if hasattr(target, attribute):
                    current_value = getattr(target, attribute)
                    setattr(target, attribute, current_value + value)
                
                effect = SkillEffect(
                    target_id=target.id,
                    effect_value=value,
                    effect_type=f"buff_{attribute}"
                )
                effects.append(effect)
            
            elif effect_type == "debuff":
                # 属性减益
                attribute = effect_data.get("attribute")
                value = effect_data.get("value", 0)
                duration = effect_data.get("duration", 1)
                chance = effect_data.get("chance", 100)
                
                if random.randint(1, 100) <= chance:
                    if hasattr(target, attribute):
                        current_value = getattr(target, attribute)
                        setattr(target, attribute, max(0, current_value + value))  # value通常是负数
                    
                    effect = SkillEffect(
                        target_id=target.id,
                        effect_value=abs(value),
                        effect_type=f"debuff_{attribute}"
                    )
                    effects.append(effect)
            
            elif effect_type == "heal_self":
                # 自我治疗
                heal_value = effect_data.get("value", 0)
                percentage = effect_data.get("percentage", 0)
                
                total_heal = heal_value + int(caster.attack * percentage / 100)
                actual_heal = caster.heal(total_heal)
                
                effect = SkillEffect(
                    target_id=caster.id,
                    effect_value=actual_heal,
                    effect_type="heal"
                )
                effects.append(effect)
            
            elif effect_type == "guaranteed_crit":
                # 必定暴击效果已在伤害计算中处理
                pass
            
            elif effect_type == "guaranteed_hit":
                # 必定命中效果已在命中计算中处理
                pass
    
    def can_target_position(self, caster_x: int, caster_y: int, target_x: int, target_y: int) -> bool:
        """检查是否可以攻击目标位置"""
        # 简单的距离检查，可以根据需要扩展
        distance = abs(caster_x - target_x) + abs(caster_y - target_y)
        max_range = 6  # 最大攻击距离，允许跨越整个战场
        return distance <= max_range
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "id": self.id,
            "name": self.name,
            "type": self.skill_type.value,
            "target_type": self.target_type.value,
            "base_value": self.base_value,
            "range_size": self.range_size,
            "cost": self.cost,
            "cooldown": self.cooldown,
            "description": self.description
        }


# 预定义技能
class SkillLibrary:
    """技能库"""
    
    @staticmethod
    def get_basic_attack() -> Skill:
        """基础攻击"""
        return Skill(
            id="basic_attack",
            name="基础攻击",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=15,
            cooldown=0,
            description="对单个敌人造成伤害"
        )
    
    @staticmethod
    def get_fireball() -> Skill:
        """火球术"""
        return Skill(
            id="fireball",
            name="火球术",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.AREA,
            base_value=20,
            range_size=1,
            cooldown=2,
            description="对目标及周围1格范围内的敌人造成火焰伤害"
        )
    
    @staticmethod
    def get_heal() -> Skill:
        """治疗术"""
        return Skill(
            id="heal",
            name="治疗术",
            skill_type=SkillType.HEAL,
            target_type=TargetType.SINGLE,
            base_value=25,
            cooldown=1,
            description="恢复单个友军的生命值"
        )
    
    @staticmethod
    def get_group_heal() -> Skill:
        """群体治疗"""
        return Skill(
            id="group_heal",
            name="群体治疗",
            skill_type=SkillType.HEAL,
            target_type=TargetType.AREA,
            base_value=15,
            range_size=2,
            cooldown=3,
            description="恢复目标及周围2格范围内友军的生命值"
        )
    
    # 战士技能
    @staticmethod
    def get_power_strike() -> Skill:
        """强力打击"""
        return Skill(
            id="power_strike",
            name="强力打击",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=25,
            cooldown=2,
            description="威力强大的重击"
        )
    
    @staticmethod
    def get_berserker_rage() -> Skill:
        """狂暴"""
        return Skill(
            id="berserker_rage",
            name="狂暴",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=30,
            cooldown=5,
            description="进入狂暴状态，大幅提升攻击力"
        )
    
    @staticmethod
    def get_blood_strike() -> Skill:
        """嗜血打击"""
        return Skill(
            id="blood_strike",
            name="嗜血打击",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=20,
            cooldown=3,
            description="攻击敌人并回复自身生命值"
        )
    
    # 坦克技能
    @staticmethod
    def get_taunt() -> Skill:
        """嘲讽"""
        return Skill(
            id="taunt",
            name="嘲讽",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=5,
            cooldown=1,
            description="强制敌人攻击自己"
        )
    
    @staticmethod
    def get_shield_wall() -> Skill:
        """盾墙"""
        return Skill(
            id="shield_wall",
            name="盾墙",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=0,
            cooldown=4,
            description="大幅提升防御力"
        )
    
    # 法师技能
    @staticmethod
    def get_ice_shard() -> Skill:
        """冰锥术"""
        return Skill(
            id="ice_shard",
            name="冰锥术",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=18,
            cooldown=1,
            description="发射冰锥，有几率冻结敌人"
        )
    
    @staticmethod
    def get_lightning_bolt() -> Skill:
        """闪电箭"""
        return Skill(
            id="lightning_bolt",
            name="闪电箭",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=15,
            cooldown=0,
            description="快速的雷电攻击"
        )
    
    # 死灵法师技能
    @staticmethod
    def get_drain_life() -> Skill:
        """生命汲取"""
        return Skill(
            id="drain_life",
            name="生命汲取",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=15,
            cooldown=2,
            description="吸取敌人生命值恢复自己"
        )
    
    @staticmethod
    def get_summon_skeleton() -> Skill:
        """召唤骷髅"""
        return Skill(
            id="summon_skeleton",
            name="召唤骷髅",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=0,
            cooldown=6,
            description="召唤骷髅战士协助战斗"
        )
    
    # 刺客技能
    @staticmethod
    def get_backstab() -> Skill:
        """背刺"""
        return Skill(
            id="backstab",
            name="背刺",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=25,
            cooldown=3,
            description="从背后攻击，必定暴击"
        )
    
    @staticmethod
    def get_shadow_step() -> Skill:
        """暗影步"""
        return Skill(
            id="shadow_step",
            name="暗影步",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=0,
            cooldown=4,
            description="瞬间移动到目标身后"
        )
    
    # 弓箭手技能
    @staticmethod
    def get_precise_shot() -> Skill:
        """精准射击"""
        return Skill(
            id="precise_shot",
            name="精准射击",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=20,
            cooldown=2,
            description="必中的精准一击"
        )
    
    @staticmethod
    def get_multi_shot() -> Skill:
        """多重射击"""
        return Skill(
            id="multi_shot",
            name="多重射击",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.AREA,
            base_value=12,
            range_size=2,
            cooldown=3,
            description="同时射击多个目标"
        )
    
    # 治疗技能（增强版）
    @staticmethod
    def get_blessing() -> Skill:
        """祝福"""
        return Skill(
            id="blessing",
            name="祝福",
            skill_type=SkillType.HEAL,
            target_type=TargetType.SINGLE,
            base_value=0,
            cooldown=5,
            description="提升友军的各项属性"
        )
    
    # 圣骑士技能
    @staticmethod
    def get_holy_strike() -> Skill:
        """神圣打击"""
        return Skill(
            id="holy_strike",
            name="神圣打击",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=22,
            cooldown=2,
            description="带有神圣力量的攻击"
        )
    
    @staticmethod
    def get_divine_protection() -> Skill:
        """神圣护盾"""
        return Skill(
            id="divine_protection",
            name="神圣护盾",
            skill_type=SkillType.HEAL,
            target_type=TargetType.SINGLE,
            base_value=0,
            cooldown=4,
            description="为友军提供伤害减免"
        )
    
    # 德鲁伊技能
    @staticmethod
    def get_nature_heal() -> Skill:
        """自然治疗"""
        return Skill(
            id="nature_heal",
            name="自然治疗",
            skill_type=SkillType.HEAL,
            target_type=TargetType.SINGLE,
            base_value=18,
            cooldown=1,
            description="持续恢复生命值"
        )
    
    @staticmethod
    def get_thorn_strike() -> Skill:
        """荆棘打击"""
        return Skill(
            id="thorn_strike",
            name="荆棘打击",
            skill_type=SkillType.DAMAGE,
            target_type=TargetType.SINGLE,
            base_value=16,
            cooldown=1,
            description="自然魔法攻击"
        )
    
    @staticmethod
    def get_wild_growth() -> Skill:
        """野性成长"""
        return Skill(
            id="wild_growth",
            name="野性成长",
            skill_type=SkillType.HEAL,
            target_type=TargetType.AREA,
            base_value=0,
            range_size=2,
            cooldown=6,
            description="提升友军生命值上限"
         )
    
    @staticmethod
    def create_skill_from_id(skill_id: str) -> Skill:
        """根据技能ID创建技能实例"""
        skill_methods = {
            "basic_attack": SkillLibrary.get_basic_attack,
            "fireball": SkillLibrary.get_fireball,
            "heal": SkillLibrary.get_heal,
            "group_heal": SkillLibrary.get_group_heal,
            "power_strike": SkillLibrary.get_power_strike,
            "berserker_rage": SkillLibrary.get_berserker_rage,
            "blood_strike": SkillLibrary.get_blood_strike,
            "taunt": SkillLibrary.get_taunt,
            "shield_wall": SkillLibrary.get_shield_wall,
            "ice_shard": SkillLibrary.get_ice_shard,
            "lightning_bolt": SkillLibrary.get_lightning_bolt,
            "drain_life": SkillLibrary.get_drain_life,
            "summon_skeleton": SkillLibrary.get_summon_skeleton,
            "backstab": SkillLibrary.get_backstab,
            "shadow_step": SkillLibrary.get_shadow_step,
            "precise_shot": SkillLibrary.get_precise_shot,
            "multi_shot": SkillLibrary.get_multi_shot,
            "blessing": SkillLibrary.get_blessing,
            "holy_strike": SkillLibrary.get_holy_strike,
            "divine_protection": SkillLibrary.get_divine_protection,
            "nature_heal": SkillLibrary.get_nature_heal,
            "thorn_strike": SkillLibrary.get_thorn_strike,
            "wild_growth": SkillLibrary.get_wild_growth
        }
        
        if skill_id not in skill_methods:
            raise ValueError(f"未知的技能ID: {skill_id}")
        
        return skill_methods[skill_id]()
    
    @staticmethod
    def get_all_skill_ids() -> List[str]:
        """获取所有可用的技能ID列表"""
        return [
            "basic_attack", "fireball", "heal", "group_heal",
            "power_strike", "berserker_rage", "blood_strike",
            "taunt", "shield_wall", "ice_shard", "lightning_bolt",
            "drain_life", "summon_skeleton", "backstab", "shadow_step",
            "precise_shot", "multi_shot", "blessing", "holy_strike",
            "divine_protection", "nature_heal", "thorn_strike", "wild_growth"
        ]